﻿using System;
using Transformable_Engine_v2.Engine.GameObjects.Containers;

namespace Project_Maverick.Screen.Common.Menu.GridMenu
{
    public class GridMenu : Container
    {
        private readonly GridMenuItem[,] _menu;
        private int _cursorX, _cursorY;
        private readonly GridMenuCursor _cursor;

        public bool AllowWrapHorizontal { get; set; }
        public bool AllowWrapVertical { get; set; }
        public int CursorTransitionTime { get; set; }

        public GridMenu(int menuSizeX, int menuSizeY, GridMenuCursor cursor)
        {
            _menu = new GridMenuItem[menuSizeX, menuSizeY];
            AllowWrapHorizontal = true;
            AllowWrapVertical = true;
            CursorTransitionTime = 500;

            _cursorX = 0;
            _cursorY = 0;

            _cursor = cursor;
        }

        public void AddMenuItem(int positionX, int positionY, GridMenuItem item)
        {
            if(_menu[positionX, positionY] != null)
                throw new Exception("There cannot be 2 menu items in the same slot");

            _menu[positionX, positionY] = item;
            AddChildren(item);
        }

        public void Start()
        {
            ChangeCursor(0, 0, 0, 0);
        }

        public Enum Accept()
        {
            return _menu[_cursorX, _cursorY].Value;
        }

        public void MoveUp()
        {
            int startingIndex = _cursorY;

            do
            {
                _cursorY--;
                if (_cursorY == -1)
                {
                    if(AllowWrapVertical)
                        _cursorY = _menu.GetLength(1) - 1;
                    else
                    {
                        _cursorY = startingIndex;
                        return;
                    }
                }

            } while (_menu[_cursorX, _cursorY] == null && _cursorY != startingIndex);

            ChangeCursor(_cursorX, _cursorY, _cursorX, startingIndex);
        }

        public void MoveDown()
        {
            int startingIndex = _cursorY;

            do
            {
                _cursorY++;
                if (_cursorY == _menu.GetLength(1))
                {
                    if (AllowWrapVertical)
                        _cursorY = 0;
                    else
                    {
                        _cursorY = startingIndex;
                        return;
                    }
                }

            } while (_menu[_cursorX, _cursorY] == null && _cursorY != startingIndex);

            ChangeCursor(_cursorX, _cursorY, _cursorX, startingIndex);
        }

        public void MoveLeft()
        {
            int startingIndex = _cursorX;

            do
            {
                _cursorX--;
                if (_cursorX == -1)
                {
                    if (AllowWrapHorizontal)
                        _cursorX = _menu.GetLength(0) - 1;
                    else
                    {
                        _cursorX = startingIndex;
                        return;
                    }
                }

            } while (_menu[_cursorX, _cursorY] == null && _cursorX != startingIndex);

            ChangeCursor(_cursorX, _cursorY, startingIndex, _cursorY);
        }

        public void MoveRight()
        {
            int startingIndex = _cursorX;

            do
            {
                _cursorX++;
                if (_cursorX == _menu.GetLength(0))
                {
                    if (AllowWrapHorizontal)
                        _cursorX = 0;
                    else
                    {
                        _cursorX = startingIndex;
                        return;
                    }
                }

            } while (_menu[_cursorX, _cursorY] == null && _cursorX != startingIndex);

            ChangeCursor(_cursorX, _cursorY, startingIndex, _cursorY);
        }

        void ChangeCursor(int x, int y, int previousX, int previousY)
        {
            _cursorX = x;
            _cursorY = y;

            _menu[previousX, previousY].Unselect();
            _menu[x, y].Select();

            _cursor.ChangePosition(_menu[x, y].Area, CursorTransitionTime);
        }
    }
}